<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>

    </style>
    <link href="../css/control.css" rel="stylesheet">
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script id="ColorVertexShader" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec4 a_Color;
    attribute float a_Set;
    attribute vec4 a_Data;

    varying vec4 v_Color;
    varying float v_Set;
    varying vec4 v_Data;


    void main(){
        gl_Position = a_Position;
        gl_PointSize = a_Data.w;

        v_Color = a_Color;
        v_Set = a_Set;
        v_Data = a_Data;
    }
</script>
<script id="ColorFragmentShader" type="x-shader/x-fragment">
    precision mediump float;

    varying vec4 v_Color;
    varying float v_Set;
    varying vec4 v_Data;

    void main(){

        float startLess = v_Data.x;
        float endLess = v_Data.y;
        float broder = v_Data.z;
        float sRand = endLess - startLess;

        float dist = distance(gl_PointCoord, vec2(0.5,0.5));
        vec4 color = v_Color;
        
        if(dist < v_Set && dist > v_Set - broder){
            if(v_Set > startLess){
                color.a = (1.0 - (v_Set - startLess) / sRand) * 1.0;
            }    
            gl_FragColor = color;
        }
    }
</script>
<script type="module">
    import { Matrix4, Vector3, Color, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'

    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight - 4;

    const gl = canvas.getContext("webgl", { antialias: true, });

    // gl.enable(gl.DEPTH_TEST);//开始背景遮挡会频闪
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    //#endregion

    const scene = new Scene({ gl: gl });
    scene.regProgram('color', {
        program: CreateProgram(gl,
            document.querySelector('#ColorVertexShader').innerText,
            document.querySelector('#ColorFragmentShader').innerText),
        attribs: [
            'a_Position',
            'a_Color', 'a_Set', 'a_Position', 'a_Data',
        ],
        uniforms: [

        ]
    })




    //默认的值
    const data = {
        index: 0,

        startLess: 0.0,//衰减开始
        endLess: 0.5,//衰减结束
        broder: 0.03,//宽度
        pointSize: 100,//直径

        S: 0.6,//扩散速度
        isRandomColor: 1,//随机颜色

        a_Position: [0, 0, 0],
        a_Color: [1, 1, 1, 1],
        a_Set: 0.0,
        a_Data: [0, 0, 0, 0],
    };

    const dataArr = [];
    let face = null;
    let publiclyIndex = 0;

    //#region 控制框

    let control = new Control();
    control.add({
        name: '扩散速度',
        max: 1, min: 0.01, value: data.S, step: 0.01,
        action: function (value) {
            data.S = Number(value);
        }
    }).add({
        name: '随机颜色',
        max: 1, min: 0, value: data.isRandomColor, step: 1,
        action: function (value) {
            data.isRandomColor = Number(value);
        }
    }).add({
        name: '宽度',
        max: 0.5, min: 0.01, value: data.broder, step: 0.01,
        action: function (value) {
            data.broder = Number(value);
        }
    }).add({
        name: '直径',
        max: 1000, min: 1, value: data.pointSize, step: 1,
        action: function (value) {
            data.pointSize = Number(value);
        }
    }).add({
        name: '衰减开始',
        max: 0.5, min: 0.0, value: data.startLess, step: 0.01,
        action: function (value) {
            data.startLess = Number(value);
        }
    }).add({
        name: '衰减结束',
        max: 0.5, min: 0.0, value: data.endLess, step: 0.01,
        action: function (value) {
            data.endLess = Number(value);
        }
    });

    //#endregion


    //main







    canvas.addEventListener('pointerdown', function (event) {
        const { clientX, clientY } = event;

        const [x, y] = getViewPosi(clientX, clientY);

        createData(x, y);
    })

    function createData(x, y) {
        let newData = {};
        Object.assign(newData, data);

        newData.a_Position = [x, y, 0];
        newData.index = publiclyIndex++;

        if (newData.isRandomColor) {
            newData.a_Color = [Math.random(), Math.random(), Math.random(), 1];
        }

        dataArr.push(newData);
    }

    function createElemenet(data) {
        face = new Obj3D({
            geo: new Geo({
                data: {
                    'a_Position': { size: 3, array: new Float32Array() },
                    'a_Color': { size: 4, array: new Float32Array() },
                    'a_Set': { size: 1, array: new Float32Array() },
                    'a_Data': { size: 4, array: new Float32Array() },
                }
            }),
            mat: new Mat({
                program: 'color',
                mode: ['POINTS']
            }),
        });
        return face;
    }

    function assignment() {
        let [a_Position_Arr, a_Color_Arr, a_Set_Arr, a_Data_Arr] = [[], [], [], []];

        for (let i = 0; i < dataArr.length; i++) {
            const {
                startLess, endLess, broder, pointSize,
                a_Position, a_Color, a_Set, a_Data,
                S, index
            } = dataArr[i];

            a_Position_Arr = a_Position_Arr.concat(a_Position);
            a_Color_Arr = a_Color_Arr.concat(a_Color);
            a_Set_Arr.push(a_Set * 0.01);
            a_Data_Arr.push(startLess, endLess, broder, pointSize);
        }


        if (face == null) {
            //重新创建
            face = createElemenet();
            scene.add(face);
        }

        //赋值(这个地方有多余的支出,回头再说)
        face.setAttrib('a_Position', { array: new Float32Array(a_Position_Arr) });
        face.setAttrib('a_Color', { array: new Float32Array(a_Color_Arr) });
        face.setAttrib('a_Set', { array: new Float32Array(a_Set_Arr) });
        face.setAttrib('a_Data', { array: new Float32Array(a_Data_Arr) });
    }

    function getViewPosi(x, y) {
        const [hx, hy] = [canvas.width / 2, canvas.height / 2];
        const [cx, cy] = [
            (x - hx) / hx,
            -(y - hy) / hy,
        ];
        return [cx, cy];
    }


    (function ani(time) {

        //计算值 a_Set
        for (let i = 0; i < dataArr.length; i++) {
            let { S, a_Set, endLess } = dataArr[i];

            if (a_Set > 100 * endLess) {
                dataArr.splice(i, 1);
                i--;
                continue;
            }

            dataArr[i].a_Set += S;
        }

        assignment();

        draw();

        if (time % 200 > 190) {
            // console.log(dataArr.length)
        }


        requestAnimationFrame(ani);
    })(0);


    function draw() {
        scene.draw();
    }
</script>

</html>